package com.mspbots.ticketai.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.mspbots.api.DataNotFoundException;
import com.mspbots.api.page.Page;
import com.mspbots.ticketai.graderule.StatusPointsGradeRuleInterceptor;
import com.mspbots.ticketai.model.*;
import com.mspbots.ticketai.service.BaseService;
import com.mspbots.ticketai.service.TicketService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * com.mspbots.core.ticketai.TicketServiceImpl
 *
 * @author Alex bob(https://github.com/vnobo)
 * @date Created by 2019/8/8
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TicketServiceImpl extends BaseService implements TicketService {

    @Override
    public Mono<Page<TicketOnly>> page(Map<String, Object> params, Page<TicketOnly> pageable) {
        return this.wiseClient.get("schedules/list", Map.of("tenantId", params.get("tenantId"), "conditions", "doneFlag=false and dateStart>=[2020-01-01]"))
                .map(this::getTicketSchedules).flatMap(scheduleMap ->
                        this.coreClient.get("tenant/company/watch/list", Map.of("tenantId", params.get("tenantId"), "enable", true))
                                .map(jsonNode -> this.objectMapper.convertValue(jsonNode, new TypeReference<List<TenantCompanyWatch>>() {
                                }))
                                .defaultIfEmpty(new ArrayList<>()).flatMap(companyList ->
                                this.coreClient.get("tenant/user/selectByIdentifier",
                                        Map.of("tenantId", params.get("tenantId"), "identifier", params.get("identifier") == null ? "" : params.get("identifier")), TenantUser.class)
                                        .defaultIfEmpty(new TenantUser())
                                        .flatMap(user -> this.coreClient.get("ticket/rules/tenant/board", Map.of("tenantId", params.get("tenantId")))
                                                .map(jsonNode -> this.objectMapper.convertValue(jsonNode, new TypeReference<List<TicketRule>>() {
                                                }))
                                                .flatMap(ticketRules ->
                                                        this.paramsMonoNew(params).flatMap(p -> {
                                                                    if (StringUtils.isEmpty(p.get("statusIds")) && StringUtils.isEmpty(p.get("statusAssignedIds"))) {
                                                                        return Mono.error(new DataNotFoundException("Search param [ticket status] not null of ticket rules."));
                                                                    }
                                                                    return this.coreClient.getFlux("/tickets/list-for-db", p, Ticket.class)
                                                                            .switchIfEmpty(Mono.error(new DataNotFoundException("This boards:[" + params.get("board") + "] get tickets is empty.")))
                                                                            .map(ticket -> {
                                                                                ticket.setTicketScheduleList(scheduleMap.getOrDefault(ticket.getCwId(), null));
                                                                                ticket.setIdentifier(params.getOrDefault("identifier", "").toString());
                                                                                ticket.setMemberTeamNames(user.getTeamNameList());
                                                                                ticket.setMemberSkillNames(user.getSkillNames());
                                                                                ticket.setIdentifierCwId(user.getCwUid());
                                                                                ticket.setCompanyWatchList(companyList);
                                                                                return ticket;
                                                                            })
                                                                            .flatMap(ticket -> super.graded(ticketRules, ticket))
                                                                            .sort((v1, v2) -> {
                                                                                if (pageable.getOrders().size() > 0 && "updated_time".equalsIgnoreCase(pageable.getOrders().get(0).getColumn())) {
                                                                                    if (pageable.getOrders().get(0).isAsc()) {
                                                                                        return v1.getUpdatedTime().compareTo(v2.getUpdatedTime());
                                                                                    }
                                                                                    return v2.getUpdatedTime().compareTo(v1.getUpdatedTime());
                                                                                }
                                                                                return v2.getOrder() - v1.getOrder();
                                                                            })
                                                                            .skip((pageable.getCurrent() - 1) * pageable.getSize()).take(pageable.getSize())
                                                                            .collectList()
                                                                            .map(pageable::setRecords)
                                                                            .flatMap(page -> {
                                                                                if (!CollectionUtils.isEmpty(page.getRecords())) {
                                                                                    page.setTotal(page.getRecords().get(0).getDataTotal());
                                                                                }
                                                                                return Mono.just(page);
                                                                            });
                                                                }
                                                        )
                                                )
                                        )
                        )
                );
    }

    @Override
    public Mono<Page<TicketSchedule>> assignedTicketPage(Map<String, Object> params, Page<TicketSchedule> pageable) {
        return this.wiseClient.get("schedules/list", Map.of("tenantId", params.get("tenantId"), "conditions", "doneFlag=false and dateStart>=[2020-01-01] and member/identifier=\"" + params.get("identifier") + "\" "))
                .map(this::getAssignedTicketSchedules)
                .flatMap(schedules ->
                        {
                            if (CollectionUtils.isEmpty(schedules)) {
                                return Mono.error(new DataNotFoundException("The User's Schedule Tasks is empty."));
                            }
                            String ticketIds = StringUtils.collectionToCommaDelimitedString(
                                    schedules.stream().map(TicketSchedule::getObjectId).collect(Collectors.toList()));
                            return this.coreClient.getFlux("/tickets/list-assigned-ticket",
                                    Map.of("tenantId", params.get("tenantId"), "ticketIds", ticketIds), Ticket.class)
                                    .map(t -> {
                                        TicketSchedule s = schedules.parallelStream()
                                                .filter(sc -> sc.getObjectId().equals(t.getCwId())).findAny().get();
                                        s.setCompanyName(t.getCompanyName());
                                        s.setSummary(t.getSummary());
                                        s.setContactName(t.getContactName());
                                        s.setDataTotal(t.getDataTotal());
                                        return s;
                                    })
                                    .sort(Comparator.comparing(TicketSchedule::getDateStart))
                                    .skip((pageable.getCurrent() - 1) * pageable.getSize()).take(pageable.getSize())
                                    .collectList()
                                    .map(pageable::setRecords)
                                    .flatMap(page -> {
                                        page.setTotal(page.getRecords() != null && page.getRecords().size() > 0 ? page.getRecords().get(0).getDataTotal() : 0);
                                        return Mono.just(page);
                                    });
                        }

                );
    }

    @Override
    public Flux<Map<String,Object>> getCheckStatus(Ticket ticket) {
        String conditions = "id=" + ticket.getCwId();
        return super.wiseClient.getFlux("/tickets/page", Map.of("tenantId", ticket.getTenantId(),
                "conditions", conditions))
                .flatMap(jsonNode->{
                    Integer statusId = jsonNode.get("status").get("id").asInt();
                    if (ticket.getStatusId().equals(statusId)) {
                        return Flux.just(Map.of("flag", true, "msg", "Success!"));
                    }
                    TicketTemp ticketNew = buildTicketOnly(ticket, jsonNode);
                    return this.coreClient.post("/tickets",ticketNew)
                            .map(flag ->Map.of("flag", false, "msg", "This ticket status has changed. Please re-request!"));
                });
    }

    @Override
    public Mono<TicketOnly> nextTicket(Map<String, Object> params) {
        return this.wiseClient.get("schedules/list", Map.of("tenantId", params.get("tenantId"), "conditions", "doneFlag=false and dateStart>=[2020-01-01]"))
                .map(this::getTicketSchedules).flatMap(scheduleMap ->
                        this.coreClient.get("tenant/configuration/keyword", Map.of("tenantId", params.get("tenantId"), "keyword", "isShowMRR"), TenantConfiguration.class)
                                .defaultIfEmpty(new TenantConfiguration()).flatMap(tenantConfig ->
                                this.coreClient.get("tenant/company/watch/list", Map.of("tenantId", params.get("tenantId"), "enable", true))
                                        .map(jsonNode -> this.objectMapper.convertValue(jsonNode, new TypeReference<List<TenantCompanyWatch>>() {
                                        }))
                                        .defaultIfEmpty(new ArrayList<>()).flatMap(companyList ->
                                        this.coreClient.get("tenant/user/selectByIdentifier",
                                                Map.of("tenantId", params.get("tenantId"), "identifier", params.get("identifier") == null ? "" : params.get("identifier")), TenantUser.class)
                                                .defaultIfEmpty(new TenantUser()).flatMap(user ->
                                                this.coreClient.get("ticket/rules/tenant/board", Map.of("tenantId", params.get("tenantId")))
                                                        .map(jsonNode -> this.objectMapper.convertValue(jsonNode, new TypeReference<List<TicketRule>>() {
                                                        }))
                                                        .flatMap(ticketRules -> this.getRejectTickets(params)
                                                                .flatMap(rejectTicketIds ->
                                                                        this.paramsMonoNew(params)
                                                                                .flatMapMany(p -> {
                                                                                    if (StringUtils.isEmpty(p.get("statusIds")) && StringUtils.isEmpty(p.get("statusAssignedIds"))) {
                                                                                        return Mono.error(new DataNotFoundException("Search param [ticket status] not null of ticket rules."));
                                                                                    }
                                                                                    p.put("rejectTicketIds", rejectTicketIds);
                                                                                    p.put("type", "next-ticket");
                                                                                    return this.coreClient.getFlux("/tickets/list-for-db", p, Ticket.class)
                                                                                            .switchIfEmpty(Mono.error(
                                                                                                    new DataNotFoundException("This boards:[" + params.get("board") + "] get tickets is empty.")));
                                                                                })
                                                                                .map(ticket -> {
                                                                                    ticket.setTicketScheduleList(scheduleMap.getOrDefault(ticket.getCwId(), null));
                                                                                    ticket.setIdentifier(params.getOrDefault("identifier", "").toString());
                                                                                    ticket.setMemberTeamNames(user.getTeamNameList());
                                                                                    ticket.setMemberSkillNames(user.getSkillNames());
                                                                                    ticket.setIdentifierCwId(user.getCwUid());
                                                                                    ticket.setCompanyWatchList(companyList);
                                                                                    ticket.setBoardName(ticket.getExtend().get("board") == null ? null : ticket.getExtend().get("board").get("name").asText());
                                                                                    ticket.setContactPhoneNumber(ticket.getExtend().get("contactPhoneNumber") == null ? null : ticket.getExtend().get("contactPhoneNumber").asText());
                                                                                    ticket.setContactEmailAddress(ticket.getExtend().get("contactEmailAddress") == null ? null : ticket.getExtend().get("contactEmailAddress").asText());
                                                                                    ticket.setIsShowMRR("true".equalsIgnoreCase(tenantConfig.getKeywordValue()));
                                                                                    return ticket;
                                                                                })
                                                                                .flatMap(ticket -> super.graded(ticketRules, ticket))
                                                                                .sort(Comparator.comparing(TicketOnly::getOrder).reversed())
                                                                                .skip(0).take(1).next()
                                                                                .map(ticketOnly -> {
                                                                                    if ("false".equalsIgnoreCase(tenantConfig.getKeywordValue())) {
                                                                                        ticketOnly.setBillAmount(null);
                                                                                    }
                                                                                    return ticketOnly;
                                                                                })
                                                                )
                                                        )
                                        )
                                )
                        ));
    }

    private List<TicketSchedule> getAssignedTicketSchedules(JsonNode jsonNode) {
        List<TicketSchedule> scheduleList = new ArrayList<>();
        Iterator<JsonNode> scheduleNodes = jsonNode.elements();
        while (scheduleNodes.hasNext()) {
            JsonNode scheduleNode = scheduleNodes.next();
            TicketSchedule schedule = TicketSchedule.builder()
                    .cwId(scheduleNode.get("id").asLong())
                    .objectId(!ObjectUtils.isEmpty(scheduleNode.get("objectId")) ? scheduleNode.get("objectId").asLong() : 0)
                    .doneFlag(!ObjectUtils.isEmpty(scheduleNode.get("doneFlag")) ? scheduleNode.get("doneFlag").asBoolean() : null)
                    .name(!ObjectUtils.isEmpty(scheduleNode.get("name")) ? scheduleNode.get("name").asText() : null)
                    .dateStart(!StringUtils.isEmpty(scheduleNode.get("dateStart")) ?
                            LocalDateTime.parse(scheduleNode.get("dateStart").asText(), DateTimeFormatter.ISO_DATE_TIME) : null)
                    .dateEnd(!StringUtils.isEmpty(scheduleNode.get("dateEnd")) ?
                            LocalDateTime.parse(scheduleNode.get("dateEnd").asText(), DateTimeFormatter.ISO_DATE_TIME) : null)
                    .status(ObjectUtils.isEmpty(scheduleNode.get("status")) ? "" : scheduleNode.get("status").get("name").asText())
                    .build();

            JsonNode memberNode = scheduleNode.get("member");
            if (!ObjectUtils.isEmpty(memberNode)) {
                schedule.setIdentifier(memberNode.get("identifier").asText());
                schedule.setMemberId(memberNode.get("id").asLong());
            }
            scheduleList.add(schedule);
        }
        return scheduleList;
    }

    private Map<Long, List<TicketSchedule>> getTicketSchedules(JsonNode jsonNode) {
        Map<Long, List<TicketSchedule>> ticketIdScheduleMap = new HashMap<>();
        Iterator<JsonNode> scheduleNodes = jsonNode.elements();
        while (scheduleNodes.hasNext()) {
            JsonNode scheduleNode = scheduleNodes.next();
            if(ObjectUtils.isEmpty(scheduleNode.get("id"))){
                log.error(">>>schedule id is empty!!! {}",scheduleNode);
                continue;
            }
            TicketSchedule schedule = TicketSchedule.builder()
                    .cwId(scheduleNode.get("id").asLong())
                    .objectId(!ObjectUtils.isEmpty(scheduleNode.get("objectId")) ? scheduleNode.get("objectId").asLong() : 0)
                    .doneFlag(!ObjectUtils.isEmpty(scheduleNode.get("doneFlag")) ? scheduleNode.get("doneFlag").asBoolean() : null)
                    .name(!ObjectUtils.isEmpty(scheduleNode.get("name")) ? scheduleNode.get("name").asText() : null)
                    .dateStart(!StringUtils.isEmpty(scheduleNode.get("dateStart")) ?
                            LocalDateTime.parse(scheduleNode.get("dateStart").asText(), DateTimeFormatter.ISO_DATE_TIME) : null)
                    .dateEnd(!StringUtils.isEmpty(scheduleNode.get("dateEnd")) ?
                            LocalDateTime.parse(scheduleNode.get("dateEnd").asText(), DateTimeFormatter.ISO_DATE_TIME) : null)
                    .status(ObjectUtils.isEmpty(scheduleNode.get("status")) ? "" : scheduleNode.get("status").get("name").asText())
                    .build();

            JsonNode memberNode = scheduleNode.get("member");
            if (!ObjectUtils.isEmpty(memberNode)) {
                schedule.setIdentifier(memberNode.get("identifier").asText());
                schedule.setMemberId(memberNode.get("id").asLong());
            }
            if (ticketIdScheduleMap.containsKey(schedule.getObjectId())) {
                ticketIdScheduleMap.get(schedule.getObjectId()).add(schedule);
            } else {
                List<TicketSchedule> scheduleList = new ArrayList<>() {{
                    add(schedule);
                }};
                ticketIdScheduleMap.put(schedule.getObjectId(), scheduleList);
            }
        }
        return ticketIdScheduleMap;
    }

    @Override
    public Mono<Page<TicketOnly>> pageBySingleRule(Map<String, Object> params, Page<TicketOnly> pageable, TicketRule ticketRule) {
        return this.wiseClient.get("schedules/list", Map.of("tenantId", params.get("tenantId"), "conditions", "doneFlag=false and dateStart>=[2020-01-01]"))
                .map(this::getTicketSchedules).flatMap(scheduleMap ->
                        this.coreClient.get("tenant/company/watch/list", Map.of("tenantId", params.get("tenantId"), "enable", true))
                                .map(jsonNode -> this.objectMapper.convertValue(jsonNode, new TypeReference<List<TenantCompanyWatch>>() {
                                }))
                                .defaultIfEmpty(new ArrayList<>()).flatMap(companyList ->
                                this.coreClient.get("tenant/user/selectByIdentifier",
                                        Map.of("tenantId", params.get("tenantId"), "identifier", params.get("identifier") == null ? "" : params.get("identifier")), TenantUser.class)
                                        .defaultIfEmpty(new TenantUser())
                                        .flatMap(user -> this.paramsMonoNew(params).flatMap(p -> {
                                                    if (StringUtils.isEmpty(p.get("statusIds")) && StringUtils.isEmpty(p.get("statusAssignedIds"))) {
                                                        return Mono.error(new DataNotFoundException("Search param [ticket status] not null of ticket rules."));
                                                    }
                                                    return this.coreClient.getFlux("/tickets/list-for-db", p, Ticket.class)
                                                            .switchIfEmpty(Mono.error(new DataNotFoundException("This boards:[" + params.get("board") + "] get tickets is empty.")))
                                                            .map(ticket -> {
                                                                ticket.setTicketScheduleList(scheduleMap.getOrDefault(ticket.getCwId(), null));
                                                                ticket.setIdentifier(params.getOrDefault("identifier", "").toString());
                                                                ticket.setMemberTeamNames(user.getTeamNameList());
                                                                ticket.setMemberSkillNames(user.getSkillNames());
                                                                ticket.setIdentifierCwId(user.getCwUid());
                                                                ticket.setCompanyWatchList(companyList);
                                                                return ticket;
                                                            })
                                                            .flatMap(ticket -> super.graded(List.of(ticketRule), ticket))
                                                            .sort(Comparator.comparing(TicketOnly::getOrder).reversed())
                                                            .skip((pageable.getCurrent() - 1) * pageable.getSize()).take(pageable.getSize())
                                                            .collectList()
                                                            .map(pageable::setRecords)
                                                            .flatMap(page -> {
                                                                if (!CollectionUtils.isEmpty(page.getRecords())) {
                                                                    page.setTotal(page.getRecords().get(0).getDataTotal());
                                                                }
                                                                return Mono.just(page);
                                                            });
                                                }
                                                )
                                        )
                        )
                );
    }

    private Mono<Map<String, Object>> paramsMonoNew(Map<String, Object> params) {
        params.put("name", "STATUS_POINTS_GRADE_RULE");
        params.put("resources", params.get("identifier"));
        if (Boolean.parseBoolean(params.get("allAssigned").toString())) {
            return paramsMonoAssigned(params);
        }
        return paramsMonoSelected(params);
    }

    private Mono<Map<String, Object>> paramsMonoSelected(Map<String, Object> params) {
        return this.coreClient.get("ticket/rules/tenant/board", params)
                .map(ruleNode -> {
                    List<TicketRule> rules = this.objectMapper.convertValue(ruleNode, new TypeReference<>() {
                    });
                    List<Integer> boardIdList = rules.stream().map(TicketRule::getBoard).collect(Collectors.toList());
                    List<Integer> status = rules.stream()
                            .map(rule -> this.objectMapper.convertValue(rule.getParams(),
                                    new TypeReference<List<StatusPointsGradeRuleInterceptor.StatusPointsParams>>() {
                                    })
                            ).flatMap(statusList ->
                                    statusList.stream()
                                            .filter(StatusPointsGradeRuleInterceptor.StatusPointsParams::isSelected)
                                            .map(StatusPointsGradeRuleInterceptor.StatusPointsParams::getStatus)
                            ).collect(Collectors.toList());
                    return Map.of("boardIds", StringUtils.collectionToCommaDelimitedString(boardIdList),
                            "statusIds", StringUtils.collectionToCommaDelimitedString(status));
                }).map(statusStr -> {
                    params.putAll(statusStr);
                    return params;
                });
    }

    private Mono<Map<String, Object>> paramsMonoAssigned(Map<String, Object> params) {
        var boards = Arrays.stream(StringUtils.commaDelimitedListToStringArray(params.get("board").toString()))
                .map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList());
        params.remove("board");
        return this.coreClient.get("ticket/rules/tenant/board", params)
                .map(ruleNode -> {
                    List<TicketRule> rules = this.objectMapper.convertValue(ruleNode, new TypeReference<>() {
                    });
                    List<Integer> boardIds = rules.stream()
                            .filter(s -> boards.contains(s.getBoard())).map(TicketRule::getBoard).collect(Collectors.toList());
                    List<Integer> boardAssignedIds = rules.stream()
                            .filter(s -> !boards.contains(s.getBoard())).map(TicketRule::getBoard).collect(Collectors.toList());
                    List<Integer> statusIds = rules.stream()
                            .filter(s -> boards.contains(s.getBoard()))
                            .map(rule -> this.objectMapper.convertValue(rule.getParams(),
                                    new TypeReference<List<StatusPointsGradeRuleInterceptor.StatusPointsParams>>() {
                                    })
                            ).flatMap(statusList ->
                                    statusList.stream()
                                            .filter(StatusPointsGradeRuleInterceptor.StatusPointsParams::isSelected)
                                            .map(StatusPointsGradeRuleInterceptor.StatusPointsParams::getStatus)
                            ).collect(Collectors.toList());
                    List<Integer> statusAssignedIds = rules.stream()
                            .filter(s -> !boards.contains(s.getBoard()))
                            .map(rule -> this.objectMapper.convertValue(rule.getParams(),
                                    new TypeReference<List<StatusPointsGradeRuleInterceptor.StatusPointsParams>>() {
                                    })
                            ).flatMap(statusList ->
                                    statusList.stream()
                                            .filter(StatusPointsGradeRuleInterceptor.StatusPointsParams::isSelected)
                                            .map(StatusPointsGradeRuleInterceptor.StatusPointsParams::getStatus)
                            ).collect(Collectors.toList());
                    return Map.of("boardIds", StringUtils.collectionToCommaDelimitedString(boardIds),
                            "statusIds", StringUtils.collectionToCommaDelimitedString(statusIds),
                            "boardAssignedIds", StringUtils.collectionToCommaDelimitedString(boardAssignedIds),
                            "statusAssignedIds", StringUtils.collectionToCommaDelimitedString(statusAssignedIds));
                }).map(statusStr -> {
                    params.putAll(statusStr);
                    return params;
                });
    }

    private Mono<Object> getRejectTickets(Map<String, Object> params) {
        String username = params.get("username").toString();
        return this.coreClient.get("ticket/reject/user/" + username, null, TicketReject[].class)
                .defaultIfEmpty(new TicketReject[1])
                .map(rejects -> {
                    List<Long> ids = Stream.of(rejects).map(TicketReject::getTicketId).collect(Collectors.toList());
                    if (ids.size() > 0) {
                        return StringUtils.collectionToCommaDelimitedString(ids);
                    }
                    return "";
                });
    }

    private TicketTemp buildTicketOnly(Ticket tickets, JsonNode content) {
        TicketTemp ticket = TicketTemp.builder()
                .id(tickets.getId())
                .cwId(tickets.getCwId())
                .tenantId(tickets.getTenantId())
                .boardId(ObjectUtils.isEmpty(content.get("board")) ? null : content.get("board").get("id").asInt())
                .updatedBy(ObjectUtils.isEmpty(content.findValue("updatedBy")) ? null : content.findValue("updatedBy").asText())
                .owner(ObjectUtils.isEmpty(content.get("owner")) ? null : content.get("owner").get("id").asLong()).build();

        JsonNode companyNode = content.get("company");
        if (!org.springframework.util.ObjectUtils.isEmpty(companyNode)) {
            ticket.setCompanyId(companyNode.get("id").asInt());
            ticket.setCompanyName(companyNode.get("name").asText());
        }

        JsonNode priorityNode = content.get("priority");
        if (!org.springframework.util.ObjectUtils.isEmpty(priorityNode)) {
            ticket.setPriorityId(priorityNode.get("id").asInt());
            ticket.setPriorityName(priorityNode.get("name").asText());
        }

        JsonNode statusNode = content.get("status");
        if (!org.springframework.util.ObjectUtils.isEmpty(statusNode)) {
            ticket.setStatus(statusNode.get("name").asText());
            ticket.setStatusId(statusNode.get("id").asInt());
        }

        JsonNode contactNode = content.get("contact");
        if (!org.springframework.util.ObjectUtils.isEmpty(contactNode)) {
            ticket.setContactId(contactNode.get("id").asInt());
            ticket.setContactName(contactNode.get("name").asText());
        }

        JsonNode summaryNode = content.get("summary");
        if (!org.springframework.util.ObjectUtils.isEmpty(summaryNode)) {
            ticket.setSummary(summaryNode.asText());
        }

        JsonNode resourcesNode = content.get("resources");
        if (!org.springframework.util.ObjectUtils.isEmpty(resourcesNode)) {
            ticket.setResources(resourcesNode.asText());
        }

        JsonNode recordTypeNode = content.get("recordType");
        if (!org.springframework.util.ObjectUtils.isEmpty(recordTypeNode)) {
            ticket.setRecordType(recordTypeNode.asText());
        }

        JsonNode subBillingMethodNode = content.get("subBillingMethod");
        if (!org.springframework.util.ObjectUtils.isEmpty(subBillingMethodNode)) {
            ticket.setSubBillingMethod(subBillingMethodNode.asText());
        }

        JsonNode locationNode = content.get("location");
        if (!org.springframework.util.ObjectUtils.isEmpty(locationNode)) {
            ticket.setLocationName(locationNode.get("name").asText());
        }

        ticket.setCreatedTime(ObjectUtils.isEmpty(content.findValue("dateEntered")) ? null : LocalDateTime.parse(content.findValue("dateEntered").asText(),
                DateTimeFormatter.ISO_ZONED_DATE_TIME));
        ticket.setUpdatedTime(ObjectUtils.isEmpty(content.findValue("lastUpdated")) ? null : LocalDateTime.parse(content.findValue("lastUpdated").asText(),
                DateTimeFormatter.ISO_ZONED_DATE_TIME));
        ticket.setExtend(content);
        return ticket;
    }
}
